/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside.ui;

import java.io.File;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import phoside.PhosideInit;
import phoside.PhosphoProteins;
import phoside.PhosphoProteinsImpl;
import phoside.Protein;
import phoside.ProteinFilter;

import phoside.data.util.PhosphoDataUtil;

import phoside.io.xml.PhosideXmlProteinsReader;
import phoside.io.xml.PhosideXmlProteinsWriter;
import phoside.io.xml.PhosphoProteinFieldValueFormatter;

import phoside.ui.task.ProteinsReadTask;
import phoside.ui.task.ProteinsWriteTask;
import phoside.ui.task.TaskUtil;

import phoside.util.FileExtensionsFilter;
import phoside.util.FilePathParser;

/**
 *
 * @author gjj
 */
public class ProteinsFilterDialog extends javax.swing.JDialog {

    /** Creates new form Fasta2XmlDialog */
    public ProteinsFilterDialog(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        javax.swing.ButtonGroup speciesbuttonGroup = new javax.swing.ButtonGroup();
        phosphoButtonGroup = new javax.swing.ButtonGroup();
        buttonGroup1 = new javax.swing.ButtonGroup();
        javax.swing.JPanel originalPanel = new javax.swing.JPanel();
        javax.swing.JPanel originalFilePanel = new javax.swing.JPanel();
        originalFileTextField = new javax.swing.JTextField();
        javax.swing.JButton originalFileButton = new javax.swing.JButton();
        javax.swing.JPanel targetPanel = new javax.swing.JPanel();
        javax.swing.JPanel targetFilePanel = new javax.swing.JPanel();
        targetFileTextField = new javax.swing.JTextField();
        javax.swing.JButton targetFileButton = new javax.swing.JButton();
        javax.swing.JPanel OKPanel = new javax.swing.JPanel();
        OKBtn = new javax.swing.JButton();
        javax.swing.JButton cancelBtn = new javax.swing.JButton();
        javax.swing.JPanel filterPanel = new javax.swing.JPanel();
        accessionCheckBox = new javax.swing.JCheckBox();
        accessionPanel = new javax.swing.JPanel();
        javax.swing.JPanel accessionIncludePanel = new javax.swing.JPanel();
        accessionIncludeRadioButton = new javax.swing.JRadioButton();
        accessionExcludeRadioButton = new javax.swing.JRadioButton();
        javax.swing.JScrollPane accessionScrollPane = new javax.swing.JScrollPane();
        accessionTextArea = new javax.swing.JTextArea();
        speciesCheckBox = new javax.swing.JCheckBox();
        speciesPanel = new javax.swing.JPanel();
        javax.swing.JPanel speciesIncludePanel = new javax.swing.JPanel();
        speciesIncludeRadioButton = new javax.swing.JRadioButton();
        speciesExcludeRadioButton = new javax.swing.JRadioButton();
        javax.swing.JScrollPane speciesScrollPane = new javax.swing.JScrollPane();
        speciesTextArea = new javax.swing.JTextArea();
        phosphoCheckBox = new javax.swing.JCheckBox();
        phosphoPanel = new javax.swing.JPanel();
        phosphoRadioButton = new javax.swing.JRadioButton();
        nonphosphoRadioButton = new javax.swing.JRadioButton();
        rmvPhosphoCheckBox = new javax.swing.JCheckBox();
        javax.swing.JPanel kinasePanel = new javax.swing.JPanel();
        kinaseCheckBox = new javax.swing.JCheckBox();
        kinaseTextField = new javax.swing.JTextField();
        javax.swing.JPanel randomSelectPanel = new javax.swing.JPanel();
        randomSelectCheckBox = new javax.swing.JCheckBox();
        randomSelectTextField = new javax.swing.JTextField();
        javax.swing.JLabel randomSelectProteinLabel = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Filter proteins");
        getContentPane().setLayout(new java.awt.GridBagLayout());

        originalPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Original PHOSIDE XML file"));
        originalPanel.setLayout(new java.awt.GridBagLayout());

        originalFilePanel.setLayout(new java.awt.GridBagLayout());

        originalFileTextField.setToolTipText("Please select a FASTA training file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        originalFilePanel.add(originalFileTextField, gridBagConstraints);

        originalFileButton.setText("Open");
        originalFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                originalFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        originalFilePanel.add(originalFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        originalPanel.add(originalFilePanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(originalPanel, gridBagConstraints);

        targetPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Save to PHOSIDE XML file"));
        targetPanel.setMinimumSize(new java.awt.Dimension(400, 63));
        targetPanel.setPreferredSize(new java.awt.Dimension(500, 63));
        targetPanel.setLayout(new java.awt.GridBagLayout());

        targetFilePanel.setLayout(new java.awt.GridBagLayout());

        targetFileTextField.setToolTipText("Please select a FASTA training file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        targetFilePanel.add(targetFileTextField, gridBagConstraints);

        targetFileButton.setText("Open");
        targetFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                targetFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        targetFilePanel.add(targetFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        targetPanel.add(targetFilePanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(targetPanel, gridBagConstraints);

        OKBtn.setText("   OK   ");
        OKBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OKBtnActionPerformed(evt);
            }
        });
        OKPanel.add(OKBtn);

        cancelBtn.setText("Cancel");
        cancelBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelBtnActionPerformed(evt);
            }
        });
        OKPanel.add(cancelBtn);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(OKPanel, gridBagConstraints);

        filterPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Filters"));
        filterPanel.setLayout(new java.awt.GridBagLayout());

        accessionCheckBox.setText("Filter by accessions");
        accessionCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                accessionCheckBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        filterPanel.add(accessionCheckBox, gridBagConstraints);

        accessionPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Accessions"));
        accessionPanel.setVisible(false);
        accessionPanel.setLayout(new java.awt.GridBagLayout());

        accessionIncludePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        buttonGroup1.add(accessionIncludeRadioButton);
        accessionIncludeRadioButton.setSelected(true);
        accessionIncludeRadioButton.setText("Include");
        accessionIncludePanel.add(accessionIncludeRadioButton);

        buttonGroup1.add(accessionExcludeRadioButton);
        accessionExcludeRadioButton.setText("Exclude");
        accessionIncludePanel.add(accessionExcludeRadioButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        accessionPanel.add(accessionIncludePanel, gridBagConstraints);

        accessionTextArea.setColumns(20);
        accessionTextArea.setRows(5);
        accessionScrollPane.setViewportView(accessionTextArea);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        accessionPanel.add(accessionScrollPane, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        filterPanel.add(accessionPanel, gridBagConstraints);

        speciesCheckBox.setText("Filter by species");
        speciesCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                speciesCheckBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 10;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        filterPanel.add(speciesCheckBox, gridBagConstraints);

        speciesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Species"));
        speciesPanel.setVisible(false);
        speciesPanel.setLayout(new java.awt.GridBagLayout());

        speciesIncludePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        speciesbuttonGroup.add(speciesIncludeRadioButton);
        speciesIncludeRadioButton.setText("Include");
        speciesIncludePanel.add(speciesIncludeRadioButton);

        speciesbuttonGroup.add(speciesExcludeRadioButton);
        speciesExcludeRadioButton.setText("Exclude");
        speciesIncludePanel.add(speciesExcludeRadioButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        speciesPanel.add(speciesIncludePanel, gridBagConstraints);

        speciesTextArea.setColumns(20);
        speciesTextArea.setRows(5);
        speciesScrollPane.setViewportView(speciesTextArea);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        speciesPanel.add(speciesScrollPane, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 11;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        filterPanel.add(speciesPanel, gridBagConstraints);

        phosphoCheckBox.setText("Filter by phosphorylation");
        phosphoCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                phosphoCheckBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 20;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        filterPanel.add(phosphoCheckBox, gridBagConstraints);

        phosphoPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Phospho or non-phopho"));
        phosphoPanel.setVisible(false);
        phosphoPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 5, 3));

        phosphoButtonGroup.add(phosphoRadioButton);
        phosphoRadioButton.setSelected(true);
        phosphoRadioButton.setText("Phosphoproteins only");
        phosphoPanel.add(phosphoRadioButton);

        phosphoButtonGroup.add(nonphosphoRadioButton);
        nonphosphoRadioButton.setText("Nonphosphoproteins only");
        phosphoPanel.add(nonphosphoRadioButton);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 21;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        filterPanel.add(phosphoPanel, gridBagConstraints);

        rmvPhosphoCheckBox.setText("Remove phosphorylation sites in the proteins");
        rmvPhosphoCheckBox.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                rmvPhosphoCheckBoxActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 30;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        filterPanel.add(rmvPhosphoCheckBox, gridBagConstraints);

        kinasePanel.setLayout(new java.awt.GridBagLayout());

        kinaseCheckBox.setText("Filter sites by kinase:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
        kinasePanel.add(kinaseCheckBox, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
        kinasePanel.add(kinaseTextField, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 40;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        filterPanel.add(kinasePanel, gridBagConstraints);

        randomSelectPanel.setLayout(new java.awt.GridBagLayout());

        randomSelectCheckBox.setText("Randomly select");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
        randomSelectPanel.add(randomSelectCheckBox, gridBagConstraints);

        randomSelectTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        randomSelectTextField.setText("100");
        randomSelectTextField.setMinimumSize(new java.awt.Dimension(60, 19));
        randomSelectTextField.setPreferredSize(new java.awt.Dimension(60, 19));
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(0, 3, 0, 3);
        randomSelectPanel.add(randomSelectTextField, gridBagConstraints);

        randomSelectProteinLabel.setText("proteins");
        randomSelectPanel.add(randomSelectProteinLabel, new java.awt.GridBagConstraints());

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 50;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        filterPanel.add(randomSelectPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(filterPanel, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void originalFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_originalFileButtonActionPerformed
        JFileChooser fc = new JFileChooser(PhosideInit.defaultPath);
        ArrayList<String> exts = new ArrayList<String>(1);
        String ext = "xml";
        exts.add(ext);
        fc.setFileFilter(new FileExtensionsFilter(exts,"PHOSIDE XML file (.xml)"));
        //fc.setAcceptAllFileFilterUsed(true);
        fc.setDialogTitle("Select a PHOSIDE XML file...");
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            originalFileTextField.setText(filePath);

            String fileName = FilePathParser.getName(filePath);
            targetFileTextField.setText(PhosideInit.defaultPath+File.separator+fileName+"-filtered.xml");
        }
}//GEN-LAST:event_originalFileButtonActionPerformed

    private void targetFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_targetFileButtonActionPerformed
        JFileChooser fc;
        String defFile = targetFileTextField.getText();
        if (defFile.length()>0) {
            fc = new JFileChooser(FilePathParser.getDir(defFile));
        } else {
            fc = new JFileChooser(PhosideInit.defaultPath);
        }

        String ext = "xml";
        fc.setSelectedFile(new File(defFile));
        ArrayList<String> exts = new ArrayList<String>(1);
        exts.add(ext);
        fc.setFileFilter(new FileExtensionsFilter(exts,"XML file (.xml)"));
        //fc.setAcceptAllFileFilterUsed(true);
        fc.setDialogTitle("Save to...");
        int returnVal = fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            targetFileTextField.setText(filePath);
        }
    }//GEN-LAST:event_targetFileButtonActionPerformed

    private void OKBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OKBtnActionPerformed
        String dirOriginal = originalFileTextField.getText();
        if (dirOriginal.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify a file containing the protein sequences.");
            return;
        }

        String dirXml = targetFileTextField.getText();
        if (dirXml.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify the xml file to save.");
            return;
        }

        boolean accessionFilter = accessionCheckBox.isSelected();
        if (accessionFilter && accessionTextArea.getText().length()==0) {
            JOptionPane.showMessageDialog(this, "Error: no accession was specified.");
            return;
        }

        boolean speciesFilter = speciesCheckBox.isSelected();
        if (speciesFilter && speciesTextArea.getText().length()==0) {
            JOptionPane.showMessageDialog(this, "Error: no species was specified.");
            return;
        }

        boolean kinaseFilter = kinaseCheckBox.isSelected();
        if (kinaseFilter && kinaseTextField.getText().length()==0) {
            JOptionPane.showMessageDialog(this, "Error: no kianse was specified.");
            return;
        }

        boolean randomSelectFilter = randomSelectCheckBox.isSelected();
        int nSelect = 0;
        if (randomSelectFilter) {
            if (randomSelectTextField.getText().length()==0) {
                JOptionPane.showMessageDialog(this, "Error: please select number of protein to select.");
                return;
            }

            try {
                nSelect = Integer.parseInt(randomSelectTextField.getText());
            } catch (java.lang.NumberFormatException e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(this, "Error: please select a positive number of protein to select.");
                return;
            }

            if (nSelect<=0) {
                JOptionPane.showMessageDialog(this, "Error: please select a positive number of protein to select.");
                return;
            }
        }

        if (phoside.util.IOUtil.fileExist(dirXml)) {
            int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing xml file?",
                    null, JOptionPane.YES_NO_OPTION);
            if (ret==JOptionPane.NO_OPTION) {
                return;
            }
        }

        //Reading phospho data
        PhosphoProteins phosphoData = new PhosphoProteinsImpl();
        PhosideXmlProteinsReader phosphoReader =
                new PhosideXmlProteinsReader(dirOriginal, phosphoData,
                    new PhosphoProteinFieldValueFormatter());

        ProteinsReadTask phosphoReadTask = new ProteinsReadTask(phosphoReader);
        TaskUtil.execute(phosphoReadTask);
        if (!phosphoReadTask.success()) {
            JOptionPane.showMessageDialog(this, "Failed to read the original file");
            return;
        }

        // accession filter
        if (accessionFilter) {
            final boolean accessionInclude = accessionIncludeRadioButton.isSelected();
            final HashSet accessions = new HashSet(Arrays.asList(accessionTextArea.getText().split("\n")));
            if (accessionInclude) {
                phosphoData.retainProteins(accessions);
            } else {
                phosphoData.removeProteins(accessions);
            }
        }

        // species filter
        if (speciesFilter) {
            final boolean speciesInclude = speciesIncludeRadioButton.isSelected();
            final HashSet species = new HashSet(Arrays.asList(speciesTextArea.getText().split("\n")));
            ProteinFilter filter = new ProteinFilter() {
                public boolean filter(Protein protein) {
                    String sp = protein.getSpecies();
                    if (sp==null) {
                        return !speciesInclude;
                    }

                    return species.contains(sp)==speciesInclude;
                }
            };
            phosphoData.filterProteins(filter);
        }

        // remove sites
        if (rmvPhosphoCheckBox.isSelected()) {
            Iterator<Protein> it = phosphoData.proteinIterator();
            while (it.hasNext()) {
                phosphoData.clearSites(it.next().getAccession());
            }
        }

        // kinase filter
        if (kinaseFilter) {
            String kinase = kinaseTextField.getText();
            //Pattern pattern = Pattern.compile(kinase);
            String kinaseLow = kinase.toLowerCase();
            Iterator<Protein> it = phosphoData.proteinIterator();
            while (it.hasNext()) {
                Protein protein = it.next();
                String acc = protein.getAccession();
                Set<Integer> sites = phosphoData.getSites(acc);
                Set<Integer> removeSites = new HashSet();
                for (int site : sites) {
                    List<String> notes = phosphoData.getSiteNotes(acc, site);
                    boolean matched = false;
                    if (notes!=null) {
                        for (String note : notes) {
                            if (note.startsWith("kinase:")) {
                                String[] strs = note.substring(7).split(",");
                                for (String str : strs) {
                                    //Matcher m = pattern.matcher(str);
                                    //matched = m.matches();
                                    int idx = str.toLowerCase().indexOf(kinaseLow);
                                    matched = idx>-1;
                                    if (matched)
                                        break;
                                }
                                break;
                            }
                        }
                    }
                    if (!matched)
                        removeSites.add(site);
                }
                phosphoData.removeSites(acc, removeSites);
            }
        }

        // phospho filter
        if (phosphoCheckBox.isSelected()) {
            final boolean phospho = this.phosphoRadioButton.isSelected();
            ProteinFilter filter = new ProteinFilter() {
                public boolean filter(Protein protein) {
                    Set<Integer> sites = PhosphoDataUtil.getSites(protein);
                    boolean p = sites!=null && !sites.isEmpty();

                    return phospho == p;
                }
            };
            phosphoData.filterProteins(filter);
        }

        if (randomSelectFilter) {
            List<String> proteinNames = new ArrayList(phosphoData.getProteinsAccessions());

            if (nSelect>proteinNames.size()) {
                JOptionPane.showMessageDialog(this, "There are only "+proteinNames.size()+".\nPlease select less.");
                return;
            }

            List<String> selectPro = phoside.util.SamplingUtil.resampleWithoutReplacement(proteinNames, nSelect);

            phosphoData.retainProteins(new HashSet(selectPro));
        }

        //Write to xml file
        PhosideXmlProteinsWriter writer = new PhosideXmlProteinsWriter(dirXml,
                new PhosphoProteinFieldValueFormatter());
        ProteinsWriteTask xmlWriteTask = new ProteinsWriteTask(phosphoData, writer);
        TaskUtil.execute(xmlWriteTask);
        if (!phosphoReadTask.success()) {
            JOptionPane.showMessageDialog(this, "Failed to write the xml file");
            return;
        }

        JOptionPane.showMessageDialog(this, "Done.");
        
        this.setVisible(false);
        this.dispose();
}//GEN-LAST:event_OKBtnActionPerformed

    private void cancelBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelBtnActionPerformed
        setVisible(false);
        dispose();
}//GEN-LAST:event_cancelBtnActionPerformed

    private void speciesCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_speciesCheckBoxActionPerformed
        speciesPanel.setVisible(speciesCheckBox.isSelected());
        this.pack();
    }//GEN-LAST:event_speciesCheckBoxActionPerformed

    private void phosphoCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_phosphoCheckBoxActionPerformed
        phosphoPanel.setVisible(phosphoCheckBox.isSelected());
        this.pack();
    }//GEN-LAST:event_phosphoCheckBoxActionPerformed

    private void rmvPhosphoCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rmvPhosphoCheckBoxActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_rmvPhosphoCheckBoxActionPerformed

    private void accessionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accessionCheckBoxActionPerformed
        accessionPanel.setVisible(accessionCheckBox.isSelected());
        this.pack();
    }//GEN-LAST:event_accessionCheckBoxActionPerformed


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton OKBtn;
    private javax.swing.JCheckBox accessionCheckBox;
    private javax.swing.JRadioButton accessionExcludeRadioButton;
    private javax.swing.JRadioButton accessionIncludeRadioButton;
    private javax.swing.JPanel accessionPanel;
    private javax.swing.JTextArea accessionTextArea;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JCheckBox kinaseCheckBox;
    private javax.swing.JTextField kinaseTextField;
    private javax.swing.JRadioButton nonphosphoRadioButton;
    private javax.swing.JTextField originalFileTextField;
    private javax.swing.ButtonGroup phosphoButtonGroup;
    private javax.swing.JCheckBox phosphoCheckBox;
    private javax.swing.JPanel phosphoPanel;
    private javax.swing.JRadioButton phosphoRadioButton;
    private javax.swing.JCheckBox randomSelectCheckBox;
    private javax.swing.JTextField randomSelectTextField;
    private javax.swing.JCheckBox rmvPhosphoCheckBox;
    private javax.swing.JCheckBox speciesCheckBox;
    private javax.swing.JRadioButton speciesExcludeRadioButton;
    private javax.swing.JRadioButton speciesIncludeRadioButton;
    private javax.swing.JPanel speciesPanel;
    private javax.swing.JTextArea speciesTextArea;
    private javax.swing.JTextField targetFileTextField;
    // End of variables declaration//GEN-END:variables

}
